import axios from 'axios';
import {ElMessage} from "element-plus";
import 'element-plus/es/components/message/style/css'
import router from "@/router";


// 标记Token是否正在刷新
let isRefreshing = false;
// 挂起的请求队列
let refreshSubscribers = [];

const defaultFailure = (message, code, url) => {
    console.warn(`请求地址:${url},状态码 ${code},错误信息:${message}`);
    ElMessage.warning(message);
}
const defaultError = (err) => {
    console.error(err);
    ElMessage.warning(err.message);
}

function storeToken(accessToken, refreshToken, rememberMe) {
    deleteToken()
    if (rememberMe) {
        localStorage.setItem("accessToken", accessToken);
        localStorage.setItem("refreshToken", refreshToken);
    } else {
        sessionStorage.setItem("accessToken", accessToken);
        sessionStorage.setItem("refreshToken", refreshToken);
    }
}

function getAccessToken() {
    const str = localStorage.getItem('accessToken') || sessionStorage.getItem('accessToken');
    if (!str) return null;
    return str;
}

function getRefreshToken() {
    const str = localStorage.getItem('refreshToken') || sessionStorage.getItem('refreshToken');
    if (!str) return null;
    return str;
}

function deleteToken() {
    localStorage.removeItem('accessToken');
    sessionStorage.removeItem('accessToken');
    localStorage.removeItem('refreshToken');
    sessionStorage.removeItem('refreshToken');
}

function internetPost(url, data, header, success, failure, error = defaultError) {
    axios.post(url, data, {headers: header}).then(({data}) => {
        if (data.code === 206 || data.code === 200) {
            success(data.data);
        } else {
            failure(data.message);
        }
    }).catch(err => {
        error(err);
    });
}

function internetGet(url, params, header, success, failure, error = defaultError) {
    axios.get(url, {
        headers: header,
        params: params,
    }).then(({data}) => {
        if (data.code === 206 || data.code === 200) {
            success(data.data);
        } else {
            failure(data.message);
        }
    }).catch(err => {
        error(err);
    })
}

//login export
function login(username, password, rememberMe, success, failure = defaultFailure) {
    const start = performance.now();           // ← 计时起点
    internetPost('/api/user/login', {
        username: username,
        password: password
    }, {
        'Content-Type': 'application/x-www-form-urlencoded'
    }, (data) => {
        storeToken(data.accessToken, data.refreshToken, rememberMe);
        const cost = ((performance.now() - start) / 1000).toFixed(2); // 秒
        ElMessage.success(`SuccessLogin! (${cost}s)`);               // ← 输出总耗时
        success();
    }, failure);
}

//logout export
function logout(success, failure = defaultFailure) {
    internetGet('/api/user/logout', {}, {}, () => {
        deleteToken()
        ElMessage.success('SuccessLogout!')
        success()
    }, failure)
}

//hello test export
function helloTest() {
    internetGet('/api/hello', {}, {
        'Accept': 'application/json',
    }, (response) => {
        ElMessage.success(response);
    }, {})
}

//upload export
function uploadFile(formData) {
    internetPost('/api/user/uploadFile', formData, {
        'Accept': 'application/json',
        'Content-Type': 'multipart/form-data'
    }, () => {
        ElMessage.success('SuccessUpload!')
    }, () => {
        ElMessage.error("FailedUpload!")
    })
}

//getFiled export
function getFile(fileName) {
    internetGet('api/user/getFile', {
        fileName: fileName
    }, {
        'Accept': 'application/json',
    }, (response) => {
        ElMessage.success(response);
    }, {})
}

//ai chat message
function chat(message, success) {
    internetGet('api/user/ChatClient', {
        message: message,
    }, {
        'Accept': 'application/json',
    }, (response) => {
        success(response);
    }, {})
}

//Authorization export ture or false
function isAuthorized() {
    // return false;
    return getAccessToken() == null;
    // const token = getAccessToken()
    // if (!token) return true;
    // try {
    //     const payload = JSON.parse(atob(token.split('.')[1])) // 解析 JWT 的 payload
    //     return payload.exp * 1000 < Date.now();              // exp 是秒级时间戳
    // } catch {
    //     return true // 解析失败当成过期处理
    // }
}

//registered
function UserRegister(username, password, email, code, success, failure = defaultFailure) {
    internetPost('/api/user/register', {
        username: username,
        password: password,
        email: email,
        code: code
    }, {
        'Content-Type': 'application/json',
    }, () => {
        ElMessage.success("successRegister!");
        success();
    }, failure)
}

//email send
function sendEmail(email, failure) {
    internetGet('/api/user/customEmail', {
        email: email,
        type: 'register',
    }, {
        'Accept': 'application/json',
    }, (response) => {
        ElMessage.success(response);
    }, failure)
}

//reset Account email
function sendConfirmEmail(email, success, failure = defaultFailure) {
    internetGet('/api/user/confirmEmail', {
        email: email,
        type: 'reset',
    }, {
        'Accept': 'application/json',
    }, (response) => {
        ElMessage.success(response);
        success();
    }, failure)
}

//reset Account Password
function resetAccountPassword(email, password, code, success, failure = defaultFailure) {
    internetPost('/api/user/reset', {
        email: email,
        password: password,
        code: code
    }, {
        'Content-Type': 'application/json',
    }, (response) => {
        ElMessage.success("重置成功,请登入");
        success();
    }, failure)
}

//refresh
function refreshToken(refreshToken, config) {
    return new Promise((resolve, reject) => {
        internetGet('/api/test/refresh', {
            refreshToken: refreshToken
        }, {
            'Accept': 'application/json'
        }, (data) => {
            storeToken(data.accessToken, data.refreshToken, false);
            config.headers.Authorization = `Bearer ${data.accessToken}`;
            resolve(axios(config)); // 重新发送请求
        }, (data) => {
            ElMessage.success("凭证过期,请重新登入!")
            deleteToken()
            setTimeout(() => {
                router.go(0);
            }, 2000);
        }, (errorData) => {
            if ([410, 400, 417].includes(errorData.code)) {
                deleteToken();
                reject(new Error('Refresh token invalid'));
            }
        });
    }).finally(() => {
        isRefreshing = false;
        // 触发所有挂起的请求
        refreshSubscribers.forEach(subscriber => subscriber());
        refreshSubscribers = [];
    });
}

function handleTokenRefresh(config) {
    if (!isRefreshing) {
        isRefreshing = true;
        return refreshToken(getRefreshToken(), config);
    } else {
        // 正在刷新Token，将请求加入队列
        return new Promise((resolve) => {
            refreshSubscribers.push(() => {
                config.headers.Authorization = `Bearer ${localStorage.getItem('accessToken')}`;
                resolve(axios(config));
            });
        });
    }
}

/*
    code:206获取成功
         200成功
         401 接口请求失败 accessToken失效
         402 密码错误
         403 不允许访问
         400 410 417 refreshToken
 */

// 请求拦截器：添加Token到请求头
axios.interceptors.request.use((config) => {
    //前端也放行RT
    if (config.url.includes('/api/test/refresh')) {
        return config;
    }
    const accessToken = getAccessToken();
    if (accessToken) {
        config.headers.Authorization = `Bearer ${accessToken}`;
    }
    return config;
}, (error) => {
    return Promise.reject(error);
});

//响应拦截器
axios.interceptors.response.use((response) => {
    // 2xx 范围内的状态码都会触发该函数。
    //注意 此状态码为请求状态码 是前端向后端请求的网络状态码 只要访问到网络接口正确或服务器正确启动就会被catch
    let code = response.data.code;
    switch (code) {
        case 200:
            return response;
        case 206:
            return response
        case 401:
            //accessToken失效 尝试重新获取
            return handleTokenRefresh(response.config);
        case 402:
            return response;
        default:
            return response;
    }
}, (error) => {
    //这里捕获4xx 范围内状态码
    //注意 这里只有当服务器 出现问题 或者url出现问题才会被捕获
    console.log("error");
    return Promise.reject(error);
})

export {
    login,
    logout,
    helloTest,
    isAuthorized,
    sendEmail,
    UserRegister,
    sendConfirmEmail,
    resetAccountPassword,
    uploadFile,
    getFile,
    chat
}